#include <UnitTest++.h>
#include <SGF.h>
#include <mapformat.pb.h>
#include <sstream>

std::ostream& operator <<(std::ostream& out,const Ogre::Vector3& v)
{
	std::string str;
	std::stringstream ss(str);
	ss
		<<'{'<<v.X<<','
		<<v.Y<<','
		<<v.Z<<'}';
	out<<ss.str();
	return out;
}

struct SaveDataFixture
{
	SaveDataFixture()
		:entity(),data(&entity)
	{
		data["int"]=6;
		data["string"]="Lollipop";
		data["bool"]=true;
		data["float"]=1.5f;
		data["vector"]=Ogre::Vector3(10.0f,20.0f,30.0f);
	}
	~SaveDataFixture()
	{
	}
	SGF::mapformat::Entity entity;
	SGF::SaveData data;
};

SUITE(SaveData)
{
	TEST_FIXTURE(SaveDataFixture,Initialization)
	{
		SGF::SaveData data2(&entity);
		int intVal=data2["int"];
		const char* stringVal=data2["string"];
		bool boolVal=data2["bool"];
		float floatVal=data2["float"];
		Ogre::Vector3 vectorVal=data2["vector"];
		CHECK_EQUAL(6,intVal);
		CHECK_EQUAL("Lollipop",stringVal);
		CHECK_EQUAL(true,boolVal);
		CHECK_EQUAL(Ogre::Vector3(10.0f,20.0f,30.0f),vectorVal);
		CHECK_CLOSE(1.5f,floatVal,0.01f);
	}

	TEST_FIXTURE(SaveDataFixture,Get)
	{
		int intVal=data["int"];
		const char* stringVal=data["string"];
		bool boolVal=data["bool"];
		float floatVal=data["float"];
		Ogre::Vector3 vectorVal=data["vector"];
		CHECK_EQUAL(6,intVal);
		CHECK_EQUAL("Lollipop",stringVal);
		CHECK_EQUAL(true,boolVal);
		CHECK_EQUAL(Ogre::Vector3(10.0f,20.0f,30.0f),vectorVal);
		CHECK_CLOSE(1.5f,floatVal,0.01f);
	}

	TEST_FIXTURE(SaveDataFixture,Set)
	{
		//modify
		data["int"]=7;
		data["bool"]=false;
		data["string"]="New";
		data["float"]=3.14f;
		data["vector"]=Ogre::Vector3(10.0f,0.0f,-24.5f);
		CHECK_EQUAL(7,(int)data["int"]);
		CHECK_EQUAL("New",(const char*)data["string"]);
		CHECK_EQUAL(false,(bool)data["bool"]);
		CHECK_EQUAL(Ogre::Vector3(10.0f,0.0f,-24.5f),(Ogre::Vector3)data["vector"]);
		CHECK_CLOSE(3.14f,(float)data["float"],0.01f);
		//new
		data["int2"]=100;
		data["bool2"]=false;
		data["string2"]="NewString";
		data["float2"]=3.55f;
		data["vector2"]=Ogre::Vector3(130.0f,440.0f,24.5f);
		CHECK_EQUAL(100,(int)data["int2"]);
		CHECK_EQUAL("NewString",(const char*)data["string2"]);
		CHECK_EQUAL(false,(bool)data["bool2"]);
		CHECK_EQUAL(Ogre::Vector3(130.0f,440.0f,24.5f),(Ogre::Vector3)data["vector2"]);
		CHECK_CLOSE(3.55f,(float)data["float2"],0.01f);
	}

	TEST_FIXTURE(SaveDataFixture,TypeSafety)
	{
		CHECK_THROW(int val=data["float"],SGF::InvalidTypeException);

		CHECK_THROW(int val=data["string"],SGF::InvalidTypeException);

		CHECK_THROW(int val=data["bool"],SGF::InvalidTypeException);

		CHECK_THROW(float val=data["int"],SGF::InvalidTypeException);

		CHECK_THROW(const char* val=data["vector"],SGF::InvalidTypeException);
	}
}